/**
 * 
 */
package org.softTank.BpelTranslator.Impl;

import java.io.StringWriter;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.softTank.BcpModel.BcpActivity;
import org.softTank.BcpModel.BcpAssign;
import org.softTank.BcpModel.BcpControl;
import org.softTank.BcpModel.BcpControlType;
import org.softTank.BcpModel.BcpProcess;
import org.softTank.BcpModel.BcpReceive;
import org.softTank.BpelModel.ObjectFactory;
import org.softTank.BpelModel.TDocumentation;
import org.softTank.BpelModel.TProcess;
import org.softTank.BpelModel.TSequence;
import org.softTank.BpelTranslator.PartnerLinkParser;
import org.softTank.BpelTranslator.ProcessParser;
import org.softTank.BpelTranslator.StructParser;
import org.softTank.BpelTranslator.Translator;
import org.softTank.BpelTranslator.VariableParser;

/**
 * @author Yuzone
 * 
 */
public class TranslatorImpl implements Translator {

	private PartnerLinkParser plParser;
	private VariableParser vParser;
	private StructParser sParser;
	private List<BcpAssign> assignList;

	public TranslatorImpl() {
		plParser = new PartnerLinkParserImpl(new ImportParserImpl());
		vParser = new VariableParserImpl(new ImportParserImpl());
		sParser = new StructParserImpl();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.softTank.BpelTranslator.Translator#bcp2Bpel(org.softTank.BcpModel
	 * .BcpProcess)
	 */
	@Override
	public String bcp2Bpel(BcpProcess value) throws Exception {
		TProcess process = translate(value);
		JAXBContext ctx = JAXBContext.newInstance("org.softTank.BpelModel");
		Marshaller marshaller = ctx.createMarshaller();
		ObjectFactory of = new ObjectFactory();
		StringWriter sw = new StringWriter();
		marshaller.marshal(of.createProcess(process), sw);

		return sParser.createStructDefinition(sw.toString(), assignList);
	}

	private TProcess translate(BcpProcess value) {
		TProcess process = new TProcess();
		process.setName(value.getName());
		process.setTargetNamespace("http://softtank.org");

		TDocumentation doc = new TDocumentation();
		doc.getContent().add(value.getDocumentation());
		process.getDocumentation().add(doc);

		process.setPartnerLinks(plParser.parsePartnerLink(value
				.getPartnerLinks(), process.getImport()));
		process.setVariables(vParser.parseVariable(value.getVariables(),
				process.getImport()));

		ProcessParser pParser;
		if (isSimpleProcess(value.getReceive())) {
			pParser = new SimpleProcessParserImpl(new AssignParserImpl(),
					new ActivityParserImpl());
		} else {
			pParser = new ComplexProcessParserImpl(new ActivityParserImpl(),
					new AssignParserImpl());
		}
		process.setSequence((TSequence) pParser
				.parseProcess(value.getReceive()));

		// extract struct info.
		this.assignList = pParser.extractStruct(value.getReceive());

		return process;
	}

	private boolean isSimpleProcess(BcpReceive receive) {
		BcpActivity iterator = receive;
		while (iterator.getInferiors().size() > 0) {
			if (iterator.getInferiors().size() > 1)
				return false;
			if (iterator.getInferiors().get(0) instanceof BcpControl
					&& ((BcpControl) iterator.getInferiors().get(0)).getType() == BcpControlType.LOOP)
				return false;
			iterator = iterator.getInferiors().get(0);
		}

		return true;
	}

}
